using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Protobuf;

namespace Protobuf
{
    /// <summary>
    /// Protobuf网络收发模拟器
    /// </summary>
    public class ProtobufNetworkSimulator : MonoBehaviour
    {
        // 单例实例
        private static ProtobufNetworkSimulator _instance;
        public static ProtobufNetworkSimulator Instance
        {
            get
            {
                return _instance;
            }
        }

        // 模拟网络延迟(毫秒)
        [SerializeField] private int minDelay = 100;
        [SerializeField] private int maxDelay = 500;

        // 模拟服务器数据
        private Dictionary<string, PlayerInfo> playerDatabase = new Dictionary<string, PlayerInfo>();
        private Dictionary<string, string> userTokens = new Dictionary<string, string>();

        private System.Random random = new System.Random();

        void Awake()
        {
            if (_instance != null && _instance != this)
            {
                Destroy(gameObject);
                return;
            }

            _instance = this;
            DontDestroyOnLoad(gameObject);

            // 初始化模拟数据库
            InitializeDatabase();
        }

        /// <summary>
        /// 初始化模拟数据库
        /// </summary>
        private void InitializeDatabase()
        {
            // 添加一些测试用户
            var player1 = new PlayerInfo
            {
                playerId = 10001,
                nickname = "玩家1",
                level = 15,
                exp = 12500,
                gold = 5000,
                diamond = 200
            };

            // 添加道具
            player1.items.Add(new ItemInfo { itemId = 101, count = 5 });
            player1.items.Add(new ItemInfo { itemId = 102, count = 3 });

            // 添加英雄
            player1.heroes.Add(new HeroInfo { heroId = 1, level = 10, star = 3 });
            player1.heroes.Add(new HeroInfo { heroId = 2, level = 8, star = 2 });

            playerDatabase["player1"] = player1;
            userTokens["player1_token"] = "player1";

            var player2 = new PlayerInfo
            {
                playerId = 10002,
                nickname = "玩家2",
                level = 25,
                exp = 45000,
                gold = 12000,
                diamond = 500
            };

            player2.items.Add(new ItemInfo { itemId = 101, count = 10 });
            player2.items.Add(new ItemInfo { itemId = 103, count = 2 });
            player2.heroes.Add(new HeroInfo { heroId = 1, level = 15, star = 4 });
            player2.heroes.Add(new HeroInfo { heroId = 3, level = 12, star = 3 });

            playerDatabase["player2"] = player2;
            userTokens["player2_token"] = "player2";
        }

        /// <summary>
        /// 发送登录请求
        /// </summary>
        /// <param name="request">登录请求</param>
        /// <param name="callback">回调函数</param>
        public void SendLoginRequest(LoginRequest request, Action<LoginResponse> callback)
        {
            Debug.Log($"发送登录请求: 用户名={request.name}, 密码={request.pass}, 设备ID={request.deviceId}, 平台={request.platform}");

            // 模拟网络延迟
            int delay = random.Next(minDelay, maxDelay + 1);
            StartCoroutine(DelayedResponse(delay, () => {
                ProcessLoginRequest(request, callback);
            }));
        }

        /// <summary>
        /// 处理登录请求
        /// </summary>
        /// <param name="request">登录请求</param>
        /// <param name="callback">回调函数</param>
        private void ProcessLoginRequest(LoginRequest request, Action<LoginResponse> callback)
        {
            var response = new LoginResponse();
            response.code = 0;
            response.message = "登录成功";

            // 简单的验证逻辑
            if (string.IsNullOrEmpty(request.name) || string.IsNullOrEmpty(request.pass))
            {
                response.code = 1;
                response.message = "用户名或密码不能为空";
            }
            else if (!playerDatabase.ContainsKey(request.name))
            {
                response.code = 2;
                response.message = "用户不存在";
            }
            else if (request.pass != "123456") // 简单的密码验证
            {
                response.code = 3;
                response.message = "密码错误";
            }
            else
            {
                // 登录成功，返回玩家信息
                response.playerInfo = playerDatabase[request.name].Clone();
                response.token = $"{request.name}_token";
            }

            Debug.Log($"收到登录响应: Code={response.code}, Message={response.message}");
            if (response.playerInfo != null)
            {
                Debug.Log($"玩家信息: ID={response.playerInfo.playerId}, 昵称={response.playerInfo.nickname}, 等级={response.playerInfo.level}");
            }

            callback?.Invoke(response);
        }

        /// <summary>
        /// 延迟响应协程
        /// </summary>
        /// <param name="delayMs">延迟毫秒数</param>
        /// <param name="action">要执行的操作</param>
        /// <returns></returns>
        private IEnumerator DelayedResponse(int delayMs, Action action)
        {
            yield return new WaitForSeconds(delayMs / 1000f);
            action?.Invoke();
        }

        /// <summary>
        /// 获取玩家信息(通过token)
        /// </summary>
        /// <param name="token">登录令牌</param>
        /// <returns>玩家信息</returns>
        public PlayerInfo GetPlayerInfoByToken(string token)
        {
            if (userTokens.ContainsKey(token) && playerDatabase.ContainsKey(userTokens[token]))
            {
                return playerDatabase[userTokens[token]].Clone();
            }
            return null;
        }

        /// <summary>
        /// 序列化对象并发送
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public byte[] Serialize<T>(T obj)
        {
            return ProtobufSerializer.Serialize(obj);
        }

        /// <summary>
        /// 反序列化数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        public T Deserialize<T>(byte[] data) where T : new()
        {
            return ProtobufSerializer.Deserialize<T>(data);
        }
    }
}